package tat.domain.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Observable;

import tat.domain.AllActorUseCaseRelations;
import tat.domain.TatActor;
import tat.domain.TatUseCase;
import tat.domain.UseCaseRelation;


public class AllActorUseCaseRelationsImpl implements AllActorUseCaseRelations {

    private Map<String, UseCaseRelation> map = new HashMap<String, UseCaseRelation>();
    private Map<UseCaseRelation, String> inverseMap = new HashMap<UseCaseRelation, String>();

    @Override
    public void add(final UseCaseRelation relation) {
        map.put(relation.name(), relation);
        inverseMap.put(relation, relation.name());
        relation.addObserver(this);
    }

    @Override
    public UseCaseRelation find(final String relationName) {
        return map.get(relationName);
    }

    @Override
    public void remove(final UseCaseRelation useCaseRelation) {
        map.remove(useCaseRelation.name());
        inverseMap.remove(useCaseRelation);
        useCaseRelation.deleteObserver(this);
    }

	@Override
	public String actorUseCaseRelationsAsText() {
		String text = "";
		Iterator<UseCaseRelation> relations = map.values().iterator();
		while(relations.hasNext()){
			text = text + relations.next().toString();
		}
		return text;
	}

	@Override
	public String actorUseCaseRelationsAsXML() {
		String text = "";
		Iterator<UseCaseRelation> relations = map.values().iterator();
		while(relations.hasNext()){
			text = text + relations.next().toXML();
		}
		return text;
	}

	@Override
	public UseCaseRelation[] confer() {
		return map.values().toArray(new UseCaseRelation[map.size()]);
	}

	@Override
	public boolean containsDerivedRelations(TatActor actor) {
		Collection<UseCaseRelation> relations = map.values(); 
		boolean contains = false;
	    for(UseCaseRelation relation : relations){
	    	if( relation.includesActor(actor)){
	    		contains = true;
	    	}
	    }
	    return contains;
	}

	@Override
	public boolean containsDerivedRelations(TatUseCase useCase) {
		Collection<UseCaseRelation> relations = map.values(); 
		boolean contains = false;
	    for(UseCaseRelation relation : relations){
	    	if( relation.useCase().equals(useCase)){
	    		  contains = true;
	    	}
	    }
	    return contains;
	}

	@Override
	public UseCaseRelation[] identifyDerivedRelations(TatActor actor) {
		List<UseCaseRelation> identifiedrelations = new ArrayList<UseCaseRelation>();
		Collection<UseCaseRelation> relations = map.values();
		for(UseCaseRelation relation : relations){
			if(relation.includesActor(actor)){
				identifiedrelations.add(relation);
			}
		}
		return identifiedrelations.toArray(new UseCaseRelation[identifiedrelations.size()]);
	}

	@Override
	public UseCaseRelation[] identifyDerivedRelations(TatUseCase useCase) {
		List<UseCaseRelation> identifiedrelations = new ArrayList<UseCaseRelation>();
		 Collection<UseCaseRelation> relations = map.values();
		for(UseCaseRelation relation : relations){
			if(relation.useCase().equals(useCase)){
				identifiedrelations.add(relation);
			}
		}
		return identifiedrelations.toArray(new UseCaseRelation[identifiedrelations.size()]);
	}

	@Override
	public void update(Observable o, Object arg) {
		UseCaseRelation modifiedRelation = (UseCaseRelation) o;
		String oldName = inverseMap.get(modifiedRelation);
		map.remove(oldName);
		map.put(modifiedRelation.name(), modifiedRelation);
		inverseMap.remove(modifiedRelation);
		inverseMap.put(modifiedRelation, modifiedRelation.name());
	}

}
